dfp: Insert correct preresolved hostname key in DNS cache#30784
dfp: Insert correct preresolved hostname key in DNS cache#30784abeyad merged 5 commits intoenvoyproxy:mainfrom
Conversation
Previously, preresolved hostnames didn't include the port in the `host` that is used as a key in the DNS cache. This behavior differed from the regular resolution path which always normalized the host (via DnsHostInfo::normalizeHostForDfp). There was also a bug in the DnsCacheImplTest.PreresolveSuccess test, where the preresolve hostnames config included the port in the socket address, which is not how it would normally be specified and masked this issue. This PR fixes the problem by ensuring the preresolved hostnames have the host normalized (via DnsHostInfo::normalizeHostForDfp) before inserting into the DNS cache, just like the host is normalized before retrieving from the DNS cache. The test issue is also fixed so we can now verify that the correct cache key is being used for insertion, retrieval, and removal, and test coverage is added to ensure we can fetch the cache entry correctly whether the host includes the port or not. Signed-off-by: Ali Beyad <abeyad@google.com>
| EXPECT_CALL(*resolver_, resolve("bar.baz.com", _, _)) | ||
| std::string host = "bar.baz.com"; | ||
| uint32_t port = 443; | ||
| std::string authority = host + ":" + std::to_string(port); |
There was a problem hiding this comment.
nit: I think absl::StrCat() is the canonical way to do this sort of concatenation.
There was a problem hiding this comment.
yeah i was debating whether to do that and add the new include or just use + and to_string() (since I see test code that use these quite liberally), but i just changed it to StrCat
| @@ -58,7 +58,10 @@ DnsCacheImpl::DnsCacheImpl( | |||
| // cache to load an entry. Further if this particular resolution fails all the is lost is the | |||
There was a problem hiding this comment.
(I'm trying to comment on line 56)
Wow, is this the correct type for hostname?
repeated config.core.v3.SocketAddress preresolve_hostnames = 10;
Hostname is a bizarre term for this as it seems to be a protocol (tcp/udp), an IP address, a port, and a resolver name. Am I reading that correctly? bizarre
There was a problem hiding this comment.
I was also surprised SocketAddress was used for preresolved hostnames config, and doesn't seem to be the right structure to represent a DNS cache entry. Changing it is a good idea but probably outside the scope of the PR. I do share your concern though..
| // this DNS cache asks for it. | ||
| startCacheLoad(hostname.address(), hostname.port_value(), false); | ||
| const std::string host = | ||
| DnsHostInfo::normalizeHostForDfp(hostname.address(), hostname.port_value()); |
There was a problem hiding this comment.
Do we need a runtime guard for this, since it looks like a behavior change? (Or is there some reason we're safe here)
There was a problem hiding this comment.
I was debating this myself, and could be convinced of adding a runtime guard. I just figured that no one is using this currently (preresolved hostnames config), and in any case, all that will happen if the cache key change causes a cache miss is that the DNS record will have to be fetched (which is actually what was happening previously on "production" use cases, i.e. my traffic director integration test, without us knowing about it, you can just tell from the logs).
There was a problem hiding this comment.
I think I'd be inclined to add a guard (which will default to true) since it's easy to add and better safe than sorry. I think we know that nobody is using the mobile APIs for this config, but I'm not sure if we know about DFP users in the wild?
There was a problem hiding this comment.
good point, i had assumed DFP is only used for mobile but didn't consider the possibility it's used outside of mobile. runtime guard has been added!
Signed-off-by: Ali Beyad <abeyad@google.com>
RyanTheOptimist
left a comment
There was a problem hiding this comment.
Thanks for doing this!
|
Adding @lizan as DFP owner and cross-company reviewer |
|
/retest |
lizan
left a comment
There was a problem hiding this comment.
one style nit. otherwise LGTM. @RyanTheOptimist feel free to merge.
| config_.mutable_max_hosts()->set_value(max_hosts); | ||
| if (!preresolve_hostnames.empty()) { | ||
| for (const auto& hostname : preresolve_hostnames) { | ||
| for (const auto& host_pair : preresolve_hostnames) { |
There was a problem hiding this comment.
nit:
| for (const auto& host_pair : preresolve_hostnames) { | |
| for (const auto& [host, port] : preresolve_hostnames) { |
There was a problem hiding this comment.
Thanks for the recommendation, done!
Signed-off-by: Ali Beyad <abeyad@google.com>
|
I think the protobuf check will fail until #30826 lands and is merged into this PR :( |
|
/retest |
Signed-off-by: Ali Beyad <abeyad@google.com>
|
/retest |
Previously, preresolved hostnames didn't include the port in the
hostthat is used as a key in the DNS cache. This behavior differed from the regular resolution path which always normalized the host (via DnsHostInfo::normalizeHostForDfp). There was also a bug in the DnsCacheImplTest.PreresolveSuccess test, where the preresolve hostnames config included the port in the socket address, which is not how it would normally be specified and masked this issue.This PR fixes the problem by ensuring the preresolved hostnames have the host normalized (via DnsHostInfo::normalizeHostForDfp) before inserting into the DNS cache, just like the host is normalized before retrieving from the DNS cache. The test issue is also fixed so we can now verify that the correct cache key is being used for insertion, retrieval, and removal, and test coverage is added to ensure we can fetch the cache entry correctly whether the host includes the port or not.